package com.swotxu.screwweb.util;

import cn.smallbun.screw.core.Configuration;
import cn.smallbun.screw.core.engine.EngineConfig;
import cn.smallbun.screw.core.engine.EngineFileType;
import cn.smallbun.screw.core.engine.EngineTemplateType;
import cn.smallbun.screw.core.execute.DocumentationExecute;
import cn.smallbun.screw.core.process.ProcessConfig;
import cn.smallbun.screw.core.util.StringUtils;
import com.swotxu.screwweb.config.ScrewProperties;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.util.CollectionUtils;

import javax.sql.DataSource;
import java.net.URL;

/**
 * @Date: 2021/7/12 20:23
 * @Author: xu.hai
 */
public abstract class ScrewUtil {

    public static void main(String[] args) {
        URL url = XmlConfigUtils.class.getClassLoader().getResource("screw-db.xml");
        System.out.println(System.getProperty("user.dir"));
        System.out.println(url);
        ScrewProperties bean = XmlConfigUtils.xml2bean(ScrewProperties.class, url.getPath());
        System.out.println(bean);
        ScrewProperties.ScrewDBInfo master_dfh_cfg = bean.toIdMap().get("master_dfh_cfg");
        create(master_dfh_cfg, "html");
    }

    public static EngineTemplateType getEngineTemplateType(String templateType) {
        switch (templateType) {
            case "freemarker": case "FREEMARKER": return EngineTemplateType.freemarker;
            case "velocity": case "VELOCITY": return EngineTemplateType.velocity;
            default: throw new IllegalArgumentException("非法的模板类型: " + templateType);
        }
    }

    public static EngineFileType getEngineFileType(String fileType) {
        switch (fileType) {
            case "html": case "HTML": return EngineFileType.HTML;
            case "word": case "WORD": return EngineFileType.WORD;
            case "md": case "MD": return EngineFileType.MD;
            default: throw new IllegalArgumentException("非法的文件类型: " + fileType);
        }
    }



    /**
     * 生成文档
     * @param dbInfo    配置实体
     * @param fileType  生成的文件类型
     */
    public static void create(ScrewProperties.ScrewDBInfo dbInfo, String fileType) {
        create(dbInfo, getEngineFileType(fileType));
    }
    /**
     * 生成文档
     * @param dbInfo    配置实体
     * @param fileType  生成的文件类型
     */
    public static void create(ScrewProperties.ScrewDBInfo dbInfo, EngineFileType fileType) {
        // 1、获取数据连接
        DataSource dataSource = getDataSource(dbInfo);
        // 2、生成文件配置
        EngineConfig engineConfig = getEngineConfig(dbInfo, fileType);
        // 3、配置想要忽略的表
        ProcessConfig processConfig = getProcessConfig(dbInfo);
        // 4、生成文档配置（包含以下自定义版本号、描述等配置连接）
        Configuration config = Configuration.builder()
                        .version(dbInfo.getVersion())
                        .title(StringUtils.isNotBlank(dbInfo.getTitle())? dbInfo.getTitle() : dbInfo.getId())
                        .description(dbInfo.getDescription())
                        .dataSource(dataSource)
                        .engineConfig(engineConfig)
                        .produceConfig(processConfig)
                        .build();
        // 5、执行生成
        new DocumentationExecute(config).execute();
    }

    /**
     * 获取数据连接
     * @param dbInfo    配置实体
     * @return  DataSource
     */
    private static DataSource getDataSource(ScrewProperties.ScrewDBInfo dbInfo) {
        // 数据源
        HikariConfig hikariConfig = new HikariConfig();
        hikariConfig.setDriverClassName(dbInfo.getDriverClassName());
        hikariConfig.setJdbcUrl(dbInfo.getJdbcUrl());
        hikariConfig.setUsername(dbInfo.getUsername());
        hikariConfig.setPassword(dbInfo.getPassword());
        // 设置可以获取tables remarks信息
        hikariConfig.addDataSourceProperty("useInformationSchema", "true");
        hikariConfig.setMinimumIdle(2);
        hikariConfig.setMaximumPoolSize(5);
        return new HikariDataSource(hikariConfig);
    }

    /**
     * 生成文件配置
     * @param dbInfo    配置实体
     * @param fileType  生成的文件类型
     * @return  EngineConfig
     */
    private static EngineConfig getEngineConfig(ScrewProperties.ScrewDBInfo dbInfo, EngineFileType fileType) {
        return EngineConfig.builder()
                // 生成文件路径
                .fileOutputDir(dbInfo.getFileOutputDir())
                // 文件名
                .fileName(dbInfo.getDocName())
                // 打开目录
                .openOutputDir(false)
                // 文件类型
                .fileType(fileType)
                // 生成模板实现
                .produceType(dbInfo.getProduceType()).build();
    }

    /**
     * 获取表单处理器
     * @param dbInfo    配置实体
     * @return  ProcessConfig
     */
    private static ProcessConfig getProcessConfig(ScrewProperties.ScrewDBInfo dbInfo) {
        ProcessConfig.ProcessConfigBuilder builder = ProcessConfig.builder();
        // 忽略表名
        if (!CollectionUtils.isEmpty(dbInfo.getIgnoreTableNames())) {
            builder.ignoreTableName(dbInfo.getIgnoreTableNames());
        }
        // 忽略表前缀
        if (!CollectionUtils.isEmpty(dbInfo.getIgnoreTablePrefixs())) {
            builder.ignoreTableName(dbInfo.getIgnoreTablePrefixs());
        }
        // 忽略表后缀
        if (!CollectionUtils.isEmpty(dbInfo.getIgnoreTableSuffixs())) {
            builder.ignoreTableName(dbInfo.getIgnoreTableSuffixs());
        }
        // 指定生成表名
        if (!CollectionUtils.isEmpty(dbInfo.getDesignatedTableNames())) {
            builder.ignoreTableName(dbInfo.getDesignatedTableNames());
        }
        // 指定生成表前缀
        if (!CollectionUtils.isEmpty(dbInfo.getDesignatedTablePrefixs())) {
            builder.ignoreTableName(dbInfo.getDesignatedTablePrefixs());
        }
        // 指定生成表后缀
        if (!CollectionUtils.isEmpty(dbInfo.getDesignatedTableSuffixs())) {
            builder.ignoreTableName(dbInfo.getDesignatedTableSuffixs());
        }
        return builder.build();
    }
}
